【新機能】Amazon AuroraからLambdaを呼べるようになりました
ウィスキー、シガー、パイプをこよなく愛する大栗です。
本日Auroraで新しい機能が発表されました。なんとAuroraの中からLambdaを呼び出す事ができるようになりました!さっそく試してみました。
2017年2月現在AuroraがPrivate Subnetに有ってもLambdaをcallすることが可能になっています。
Amazon Aurora Update – Call Lambda Functions From Stored Procedures; Load Data From S3 Release: Amazon RDS on 2016-10-18
どういう機能?
一言で書くと、『AuroraのストアドプロシージャでLambdaをInvokeできる』機能です。
ドキュメントによると、ストアドプロシージャは以下の通りです。
シンタックス
CALL mysql.lambda_async ( lambda_function_ARN, lambda_function_input )
パラメータ
- lambda_function_ARN 呼び出すLambdaファンクションのARN
- lambda_function_input Lambfaファンクションを呼び出すJSON形式の入力文字列
なお、Aurora上でmysql.lambda_async
の定義を確認すると以下のようになっています。
mysql> show create procedure mysql.lambda_async \G *************************** 1. row *************************** Procedure: lambda_async sql_mode: NO_ENGINE_SUBSTITUTION Create Procedure: CREATE DEFINER=`rdsadmin`@`localhost` PROCEDURE `lambda_async`(IN functionName VARCHAR(1600), IN inputPayload VARCHAR(65535)) READS SQL DATA DETERMINISTIC BEGIN AWSLAMBDA(functionName,inputPayload,'0'); END character_set_client: utf8 collation_connection: utf8_general_ci Database Collation: latin1_swedish_ci
Lambda呼出しを試してみる
AuroraからLambdaを呼出して、SNS経由でメールを送信してみます。リージョンは東京で構築しています。
Auroraを起動する
今回は、以下のようにAuroraを起動しました。なお、既存のAuroraインスタンスでLambdaを実行する場合には、バージョンを1.8に上げる必要があるのでご注意ください。
- リージョン:東京
- インスタンスクラス:db.r3.large
- マルチAZ:No
- サブネットグループ:Default(デフォルトVPC)
- パブリックアクセス可能:いいえ
- Availability Zone:ap-northeast-1a
- パラメータグループ:新規で作成したもの
SNSトピックを作成する
SNSトピックを作成して、Subscriptionをメールで作成します。登録メールでConfirmします。
IAM Roleを作成する
Lambda用Role
以下の内容でIAM Roleを作成します。
- ロール名:(任意に設定してください)
- AWS サービスロール:AWS Lambda
- アタッチするポリシー:AmazonSNSFullAccess
RDS用Role
一度、以下の内容でRoleを作成します。
- ロール名:(任意に設定してください)
- AWS サービスロール:Amazon RDS
- アタッチするポリシー:無し
作成した後に、アクセス許可でAWSLambdaRole
管理ポリシーをアタッチします。
Lambdaファンクションを作成する
SNSを呼び出すLambdaファンクションを作成します。 ここでは、以下の内容で作成しています。
- Runtime:Python 2.7
- Handler:lambda_function.lambda_handler
- Role:先程作成したLambda用Role
スクリプト内のTopicArn
の中身はSNSトピックのARNに置換します。
import boto3 sns = boto3.client('sns') def lambda_handler(event, context): return sns.publish( TopicArn='arn:aws:sns:ap-northeast-1:123456789012:AuroraLambda', Message=event['message'], Subject=event['subject'], MessageStructure='string' )
AuroraにIAM Roleを設定する
AuroraへIAM Roleを設定するには、AuroraクラスタとDBクラスタパラメータグループの2箇所で設定する必要があります。
Auroraクラスタの設定
作成したAuroraのクラスタの画面にIAM ロールの管理
というボタンが増えているので、クリックします。
先程作成したRDS用Roleを選択します。
DBクラスタパラメータグループの設定
aws_default_lambda_role
で先程作成したRDS用RoleのARNを入力して変更を保存します。設定後にAuroraインスタンスのDBクラスタパラメータグループがpending-reboot
になっていた場合はインスタンスの再起動を行ってください。
Lambdaを起動する
Auroraにログインして、以下のコマンドを実行してみます。(第一引数は作成したLambdaファンクションをARNに変更してください)
mysql> CALL mysql.lambda_async('arn:aws:lambda:ap-northeast-1:123456789012:function:tosns', '{"subject" : "Aurora", "message" : "Test Aurora Invoke"}');
しかし、以下のエラーメッセージが表示されてしまいます。
ERROR 1873 (HY000): Lambda API returned error: Network Connection. Unable to connect to endpoint
Lambdaを実行するAuroraインスタンスは、VPC経由でLambdaエンドポイントへアクセスできるネットワーク環境が必要のようです。今回はデフォルトVPCに配置しているためパブリックアクセス可能にするだけで済みますが、Privateサブネットに配置している場合にはPublicサブネットへ移行するかRoute Tableでパブリックにする必要があります。ご注意ください。
Auroraインスタンスをパブリックアクセス可能にして再度実行します。(第一引数は作成したLambdaファンクションをARNに変更してください)
2017年2月現在AuroraがPrivate Subnetに有ってもLambdaをcallすることが可能になっています。
mysql> CALL mysql.lambda_async('arn:aws:lambda:ap-northeast-1:123456789012:function:tosns', '{"subject" : "Aurora", "message" : "Test Aurora Invoke"}'); Query OK, 0 rows affected (0.12 sec)
この様にメールが届きます。
さいごに
いかがでしょうか。ストアドプロシージャとしてLambdaを呼べるため、トリガーに設定することでAuroraで更新したデータをDynamoDBに保存したりSNSで通知したりすることができます。データ更新の確認をPullではなくPushで出来るようになったのでリアクティブなアーキテクチャを構築する事ができます。
しかし、既存のAuroraインスタンスでLambdaを実行させたい場合には、ネットワーク構成を変更する必要があるかもしれません。Privateサブネットでも、既存の拡張モニタリングなどはCloudWatch Logsにデータを保存できましたが、今回の機能はネットワーク環境を考慮する必要があるので既存の環境をよく確認してから適用しましょう。